package com.tidu.strategy;

import com.tidu.strategy.abstractSync.AbstractSyncStrategy;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Slf4j
public class DataBaseSyncStrategy extends AbstractSyncStrategy {

    private final MultiTableSyncStrategy multiTableSyncStrategy;
    private final List<String> tableNames;

    public DataBaseSyncStrategy(DataSource sourceDataSource, DataSource targetDataSource) {
        super(sourceDataSource, targetDataSource);

        String sourceDatabase = getDatabaseName(sourceDataSource);
        this.tableNames = getTablesFromDatabase(sourceDataSource, sourceDatabase);
        this.multiTableSyncStrategy = new MultiTableSyncStrategy(tableNames, sourceDataSource, targetDataSource);
    }

    /**
     * 从数据源中获取数据库名
     */
    private String getDatabaseName(DataSource dataSource) {
        try (Connection conn = dataSource.getConnection()) {
            return conn.getCatalog(); // 获取当前数据库名称
        } catch (SQLException e) {
            throw new RuntimeException("Failed to get database name", e);
        }
    }

    /**
     * 查询数据库中所有用户表（排除系统表）
     */
    private List<String> getTablesFromDatabase(DataSource dataSource, String databaseName) {
        String sql = "SELECT TABLE_NAME FROM information_schema.tables " +
                "WHERE TABLE_SCHEMA = ? AND TABLE_TYPE = 'BASE TABLE'";

        try (Connection conn = dataSource.getConnection();
             var stmt = conn.prepareStatement(sql)) {

            stmt.setString(1, databaseName);
            try (ResultSet rs = stmt.executeQuery()) {
                List<String> tables = new ArrayList<>();
                while (rs.next()) {
                    tables.add(rs.getString("TABLE_NAME"));
                }
                log.info("Found tables in database '{}': {}", databaseName, tables);
                return tables;
            }
        } catch (SQLException e) {
            throw new RuntimeException("Failed to fetch tables from database: " + databaseName, e);
        }
    }

    /**
     * 启动整个数据库的同步任务
     */
    @Override
    public List<Map<String, Object>> fetchData() {
        log.info("Starting database sync for all tables in source database.");
        return multiTableSyncStrategy.fetchData();
    }

    /**
     * 写入数据（由 fetchData 内部调用）
     */
    @Override
    public void writeData(List<Map<String, Object>> records) {
        // 由 MultiTableSyncStrategy 内部处理
    }

    /**
     * 判断整个数据库是否同步完成
     */
    @Override
    public boolean isCompleted() {
        return multiTableSyncStrategy.isCompleted();
    }

    /**
     * 获取整个数据库的同步进度
     */
    @Override
    public String getProgress() {
        return multiTableSyncStrategy.getProgress();
    }

    /**
     * 获取当前同步的表名列表（供调试/监控使用）
     */
    public List<String> getTableNames() {
        return Collections.unmodifiableList(tableNames);
    }
}
